package logic

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"github.com/zeromicro/go-zero/core/logx"
	"net/http"
	"strings"
	"time"
	"yunzhan/alert-server/internal/model/notifiers"
	"yunzhan/alert-server/internal/svc"
	"yunzhan/alert-server/internal/types"
)

type AlertLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// NewAlertLogic 创建一个新的 AlertLogic 实例
func NewAlertLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AlertLogic {
	return &AlertLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// StartAlertMonitoring 启动告警监控
func (l *AlertLogic) StartAlertMonitoring() {
	ticker := time.NewTicker(10 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			rules, err := l.svcCtx.AlertRuleModel.FindAllEnabled()
			if err != nil {
				l.Logger.Errorf("Error fetching alert rules: %v", err)
				continue
			}

			// 读取告警规则
			for _, rule := range rules {
				// 通过告警规则中配置的节点信息查询监控数据
				components, err := l.svcCtx.ComponentInfoModel.FindByComponentNameAndRole(rule.ComponentName, rule.ComponentRole)
				if err != nil {
					l.Logger.Errorf("Error fetching component info: %v", err)
					continue
				}

				for _, component := range components {
					if !component.Status {
						message := fmt.Sprintf(`%v 主机: %s %s %s 进程不可用, 请查看日志排查进程是否异常`,
							component.UpdatedAt,
							component.NodeHost,
							component.ComponentName,
							component.ComponentRole)
						l.sendAlerts(rule, message)
					}
				}
			}
		case <-l.ctx.Done():
			l.Logger.Info("Alert monitoring stopped.")
			return
		}
	}
}

// StartAlertMonitoring 启动告警监控
func StartAlertMonitoring(ctx context.Context, svcCtx *svc.ServiceContext) {
	alertLogic := NewAlertLogic(ctx, svcCtx)
	go alertLogic.StartAlertMonitoring()
}

func (l *AlertLogic) sendAlerts(rule types.AlertRule, message string) {

	var notificationConfig []types.NotificationConfigItem
	if err := json.Unmarshal([]byte(rule.NotificationConfig), &notificationConfig); err != nil {
		errMsg := fmt.Sprintf("解析 notification_config 失败: %v", err)
		logx.Errorf(errMsg)
	}

	for _, config := range notificationConfig {
		l.Logger.Infof("Notification ID: %d, Name: %s", config.NotificationID, config.NotificationType)
		notification, err := l.svcCtx.NotificationModel.FindByTypeAndID(config.NotificationID, config.NotificationType)
		if err != nil {
			l.Logger.Errorf("Error fetching notifications for rule %d: %v", config.NotificationID, err)
			return
		}
		switch strings.ToLower(notification.Type) {
		case "email":
			l.sendEmail(notification.Config, message)
		case "dingtalk":
			l.sendDingTalk(notification.Config, message)
		case "wechat":
			l.sendWeChat(notification.Config, message)
		case "webhook":
			l.sendWebhook(notification.Config, message)
		case "slack":
			l.sendSlack(notification.Config, message)
		case "sms":
			l.sendSMS(notification.Config, message)
		case "feishu":
			l.sendFeiShu(notification.Config, message)
		}
	}

}

func (l *AlertLogic) sendDingTalk(config string, message string) {
	var dingTalkConfig struct {
		WebhookURL string `json:"webhook_url"`
	}

	logx.Infof("DingTalk Config: %s", config)
	if err := json.Unmarshal([]byte(config), &dingTalkConfig); err != nil {
		l.Logger.Error("解析 DingTalk 配置失败:", err)
		return
	}

	if err := notifiers.SendDingTalkWebhook(dingTalkConfig.WebhookURL, message); err != nil {
		l.Logger.Error("发送 DingTalk 通知失败:", err)
	}
}

func (l *AlertLogic) sendWeChat(config string, message string) {
	var weChatConfig struct {
		WebhookURL string `json:"webhook_url"`
	}

	logx.Infof("WeChat Config: %s", config)
	if err := json.Unmarshal([]byte(config), &weChatConfig); err != nil {
		l.Logger.Error("解析 WeChat 配置失败:", err)
		return
	}

	if err := notifiers.SendWeChatWebhook(weChatConfig.WebhookURL, message); err != nil {
		l.Logger.Error("发送 WeChat 通知失败:", err)
	}
}

func (l *AlertLogic) sendWebhook(config string, message string) {
	var webhookConfig struct {
		URL string `json:"url"`
	}

	if err := json.Unmarshal([]byte(config), &webhookConfig); err != nil {
		l.Logger.Error("解析 Webhook 配置失败:", err)
		return
	}

	payload := map[string]interface{}{
		"message": message,
	}

	body, err := json.Marshal(payload)
	if err != nil {
		l.Logger.Error("Failed to marshal webhook payload:", err)
		return
	}

	req, err := http.NewRequest("POST", webhookConfig.URL, bytes.NewBuffer(body))
	if err != nil {
		l.Logger.Error("创建 Webhook HTTP 请求失败:", err)
		return
	}
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		l.Logger.Error("发送 Webhook HTTP 请求失败:", err)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		l.Logger.Errorf("Webhook notification failed with status code: %d", resp.StatusCode)
		return
	}

	l.Logger.Info("Webhook 通知已成功发送.")
}

func (l *AlertLogic) sendEmail(config string, message string) {
	var emailConfig []types.EmailConfig

	logx.Infof("Email Config: %s", config)
	if err := json.Unmarshal([]byte(config), &emailConfig); err != nil {
		l.Logger.Error("解析 Email 配置失败:", err)
		return
	}

	if err := notifiers.SendEmail(emailConfig, "text/plain", message); err != nil {
		l.Logger.Error("发送 Email 通知失败:", err)
	}
}

func (l *AlertLogic) sendSlack(config string, message string) {
	var slackConfig struct {
		WebhookURL string `json:"webhook_url"`
	}
	logx.Infof("Slack Config: %s", config)
	if err := json.Unmarshal([]byte(config), &slackConfig); err != nil {
		l.Logger.Error("解析 Slack 配置失败:", err)
		return
	}

	if err := notifiers.SendSlackWebhook(slackConfig.WebhookURL, message); err != nil {
		l.Logger.Error("发送 Slack 通知失败:", err)
	}
}

func (l *AlertLogic) sendSMS(config string, message string) {
	var smsConfig []notifiers.SMSConfig
	logx.Infof("SMS Config: %s", config)
	if err := json.Unmarshal([]byte(config), &smsConfig); err != nil {
		l.Logger.Error("解析 SMS 配置失败:", err)
		return
	}

	if err := notifiers.SendSMS(smsConfig, message); err != nil {
		l.Logger.Error("发送 SMS 通知失败:", err)
	}
}

func (l *AlertLogic) sendFeiShu(config string, message string) {
	var feiShuConfig struct {
		WebhookURL string `json:"webhook_url"`
	}

	logx.Infof("FeiShu Config: %s", config)
	if err := json.Unmarshal([]byte(config), &feiShuConfig); err != nil {
		l.Logger.Error("解析 FeiShu 配置失败:", err)
		return
	}

	if err := notifiers.SendFeiShuWebhook(feiShuConfig.WebhookURL, message); err != nil {
		l.Logger.Error("发送 FeiShu 通知失败:", err)
	}
}
